﻿namespace WMM.Tapioca.Utilities
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Net;
    using System.Net.Cache;
    using System.Xml;
    using System.IO;
    using System.Configuration;

    /// <summary>
    /// TODO: Update summary.
    /// </summary>
    public class XmlCachingResolver : XmlUrlResolver
    {
        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        bool enableHttpCaching;
        ICredentials credentials;
        public bool UseProxy;

        private WebProxy proxyServer;

        public WebProxy ProxyServer
        {
            get { return proxyServer; }
            set { proxyServer = value; }
        }

        //resolve resources from cache (if possible) when enableHttpCaching is set to true
        //resolve resources from source when enableHttpcaching is set to false 
        public XmlCachingResolver(bool enableHttpCaching)
        {
            this.enableHttpCaching = enableHttpCaching;
            
            //proxyServer = GetProxy();
        }

        //resolve resources from cache (if possible) when enableHttpCaching is set to true
        //resolve resources from source when enableHttpcaching is set to false 
        public XmlCachingResolver(bool enableHttpCaching, bool useProxy)
        {
            this.enableHttpCaching = enableHttpCaching;
            this.UseProxy = useProxy;

            if (useProxy)
            {                
                proxyServer = GetProxy();
            }            
        }


        private WebProxy GetProxy()
        {            
            string proxyServer = ConfigurationManager.AppSettings["ProxyServer"];
            string domain = ConfigurationManager.AppSettings["Domain"];
            string user = ConfigurationManager.AppSettings["User"];
            string password = ConfigurationManager.AppSettings["Password"];

            if (!string.IsNullOrEmpty(user))
            {
                ICredentials myCred = new NetworkCredential(user, password, domain);

                return new WebProxy(proxyServer, true, new string[] { }, myCred);
            }

            return null;
        }


        public WebProxy GetProxy(string proxy)
        {
            string[] proxyParameters = proxy.Split('@');

            if (proxyParameters.Length > 1)
            {
                string proxyServer = proxyParameters[1];
                int pos1 = proxyParameters[0].IndexOf(@"//");
                string[] userData = proxyParameters[0].Substring(pos1 + 2).Split(':');
                string user = userData[0];
                string password = userData[1];
                string domain = "";
                ICredentials myCred = new NetworkCredential(user, password, domain);

                return new WebProxy(proxyServer, true, new string[] { }, myCred);
            }
            else
            {
                string proxyServer = proxyParameters[0];
                ICredentials myCred = new NetworkCredential();

                return new WebProxy(proxyServer, true, new string[] { }, myCred);
            }            
        }


        public override ICredentials Credentials
        {
            set
            {
                credentials = value;
                base.Credentials = value;
            }
        }


        public override object GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn)
        {
            if (absoluteUri == null)
            {
                throw new ArgumentNullException("absoluteUri");
            }

            //resolve resources from cache (if possible)
            if (absoluteUri.Scheme == "http" && enableHttpCaching && (ofObjectToReturn == null || ofObjectToReturn == typeof(Stream)))
            {
                WebRequest webReq = WebRequest.Create(absoluteUri);
                //webReq.CachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.Default);
                webReq.CachePolicy = new RequestCachePolicy(RequestCacheLevel.CacheIfAvailable);

                webReq.Proxy = ProxyServer;

                try
                {
                    WebResponse response = webReq.GetResponse();

                    log.Debug("Downloading file... Uri: " + absoluteUri.AbsoluteUri + " IsFromCache? " + response.IsFromCache);
                    return response.GetResponseStream();
                }
                catch (WebException ex)
                {
                    //log.Error("Validation error on schema:" + absoluteUri + ". " + ex.Message);
                    throw ex;
                }
            }
            //otherwise use the default behavior of the XmlUrlResolver class (resolve resources from source)
            else
            {
                log.Debug("Use the default behavior of the XmlUrlResolver class to loaded resource: " + absoluteUri.AbsoluteUri);
                return base.GetEntity(absoluteUri, role, ofObjectToReturn);
            }
        }
    }


}
